﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Vibz.SharePoint.Query;

namespace Vibz.TeamAssignment.Sharepoint
{
    internal static class SPListCache
    {
        class SPListObject
        {
            public object ListObject
            {
                get;
                set;
            }
            public DateTime CreationTime
            {
                get;
                set;
            }
            public int ExpiryDuration
            {
                get;
                set;
            }
            public SPListObject(object obj, int expDuration)
            {
                ListObject = obj;
                ExpiryDuration = expDuration;
                CreationTime = DateTime.Now;
            }
        }
        public static void Clear()
        {
            _CacheList.Clear();
            Console.WriteLine(DateTime.Now.ToLongTimeString() + "\tCache Clear");
        }
        static Dictionary<string, SPListObject> _CacheList = new Dictionary<string, SPListObject>();
        public delegate List<T> GetListDelegate<T>(Expression exp);
        public delegate T GetItemOnIDDelegate<T>(int id);
        public delegate T GetItemOnNameDelegate<T>(string name);
        internal static List<T> GetList<T>(string key, GetListDelegate<T> getListFunction, Expression exp, int expiryDuration)
        {
            try
            {
                lock(_CacheList)
                {
                    Console.WriteLine(DateTime.Now.ToLongTimeString() + "\tGetList: " + getListFunction.Method.Name + ": " + key);
                    if(!_CacheList.ContainsKey(key))
                    {
                        _CacheList.Add(key, new SPListObject(getListFunction(exp), expiryDuration));
                        Console.WriteLine(DateTime.Now.ToLongTimeString() + "\tGetList: " + getListFunction.Method.Name + ": Added");
                    }
                    else if(DateTime.Now.CompareTo(_CacheList[key].CreationTime.AddSeconds((double)_CacheList[key].ExpiryDuration)) > 0)
                    {
                        _CacheList[key] = new SPListObject(getListFunction(exp), expiryDuration);
                        Console.WriteLine(DateTime.Now.ToLongTimeString() + "\tGetList: " + getListFunction.Method.Name + ": Updated");
                    }
                    Console.WriteLine(DateTime.Now.ToLongTimeString() + "\t-GetList: " + getListFunction.Method.Name + ": " + key);
                }
            }
            catch(Exception exc)
            {
                throw new Exception("Error while adding " + key + ". " + exc.Message);
            }
            List<T> retValue = (List<T>)_CacheList[key].ListObject;
            if(retValue == null)
                retValue = new List<T>();
            return retValue;

        }
        internal static void AddItem<T>(string key, T item, int expiryDuration)
        {
            try
            {
                lock(_CacheList)
                {
                    if(!_CacheList.ContainsKey(key))
                        _CacheList.Add(key, new SPListObject(item, expiryDuration));
                    else
                        _CacheList[key] = new SPListObject(item, expiryDuration);
                }
                Console.WriteLine(DateTime.Now.ToLongTimeString() + "\tAddItem: " + key);
            }
            catch(Exception exc)
            {
                throw new Exception("Error while adding " + key + ". " + exc.Message);
            }
        }
        internal static T GetItem<T>(string key, GetItemOnIDDelegate<T> getItemFunction, int id, int expiryDuration)
        {
            try
            {
                lock(_CacheList)
                {
                    Console.WriteLine(DateTime.Now.ToLongTimeString() + "\tGetItem: " + getItemFunction.Method.Name + ": " + key + ": " + id);
                    if(!_CacheList.ContainsKey(key))
                    {
                        _CacheList.Add(key, new SPListObject(getItemFunction(id), expiryDuration));
                        Console.WriteLine(DateTime.Now.ToLongTimeString() + "\tGetItem: " + getItemFunction.Method.Name + ": Added ");
                    }
                    else if(DateTime.Now.CompareTo(_CacheList[key].CreationTime.AddSeconds((double)_CacheList[key].ExpiryDuration)) > 0)
                    {
                        _CacheList[key] = new SPListObject(getItemFunction(id), expiryDuration);
                        Console.WriteLine(DateTime.Now.ToLongTimeString() + "\tGetItem: " + getItemFunction.Method.Name + ": Updated");
                    }
                    Console.WriteLine(DateTime.Now.ToLongTimeString() + "\t-GetItem: " + getItemFunction.Method.Name + ": " + key);
                }
            }
            catch(Exception exc)
            {
                throw new Exception("Error while adding " + key + ". " + exc.Message);
            }
            T retValue = (T)_CacheList[key].ListObject;
            return retValue;

        }
        internal static T GetItem<T>(string key, GetItemOnNameDelegate<T> getItemFunction, string name, int expiryDuration)
        {
            try
            {
                lock(_CacheList)
                {
                    Console.WriteLine(DateTime.Now.ToLongTimeString() + "\tGetItem: " + getItemFunction.Method.Name + ": " + key + ": " + name);
                    if(!_CacheList.ContainsKey(key))
                    {
                        _CacheList.Add(key, new SPListObject(getItemFunction(name), expiryDuration));
                        Console.WriteLine(DateTime.Now.ToLongTimeString() + "\tGetItem: " + getItemFunction.Method.Name + ": Added ");
                    }
                    else if(DateTime.Now.CompareTo(_CacheList[key].CreationTime.AddSeconds((double)_CacheList[key].ExpiryDuration)) > 0)
                    {
                        _CacheList[key] = new SPListObject(getItemFunction(name), expiryDuration);
                        Console.WriteLine(DateTime.Now.ToLongTimeString() + "\tGetItem: " + getItemFunction.Method.Name + ": Updated");
                    }
                    Console.WriteLine(DateTime.Now.ToLongTimeString() + "\t-GetItem: " + getItemFunction.Method.Name + ": " + key);
                }
            }
            catch(Exception exc)
            {
                throw new Exception("Error while adding " + key + ". " + exc.Message);
            }
            T retValue = (T)_CacheList[key].ListObject;
            return retValue;

        }
        internal static void Expire(string key)
        {
            if(_CacheList.ContainsKey(key))
                _CacheList[key].ExpiryDuration = 0;
            Console.WriteLine(DateTime.Now.ToLongTimeString() + "\tCache Expire: " + key);
        }
    }
    
}
